package com.imooc.miaosha.service.impl;

import com.alibaba.fastjson.TypeReference;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.imooc.miaosha.Message.MiaoshaMessage;
import com.imooc.miaosha.common.Const;
import com.imooc.miaosha.config.MqSender;
import com.imooc.miaosha.dao.*;
import com.imooc.miaosha.dto.MiaoshaManageDTO;
import com.imooc.miaosha.pojo.*;
import com.imooc.miaosha.service.SecondKillService;
import com.imooc.miaosha.util.JedisUtil;
import com.imooc.miaosha.util.JsonData;
import com.imooc.miaosha.util.JsonUtil;
import com.imooc.miaosha.util.TimeUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Slf4j
@Service
public class SecondKillServiceImpl implements SecondKillService {
    @Autowired
    MiaoshaGoodsMapper miaoshaGoodsMapper;
    @Autowired
    MiaoshaOrderMapper miaoshaOrderMapper;
    @Autowired
    GoodsMapper goodsMapper;
    @Autowired
    OrderInfoMapper orderInfoMapper;
    @Autowired
    ShippingMapper shippingMapper;
    @Autowired
    MqSender mqSender;
    @Autowired
    UserMapper userMapper;

    @Transactional
    public Map<String, Object> buy(Long userId, Long secondKillId, Long shippingId, String path) {
        if (!JedisUtil.get(Const.MIAOSHA_CHECK_TOKEN, userId + ":" + secondKillId).equals(path)) {
            return this._createRetMap(Const.STATUS_CODE.FAIL_CODE, "路径不匹配");
        }
        User user = userMapper.selectByPrimaryKey(userId);
        String miaoshaJson = JedisUtil.get(Const.MIAOSHA_INFO, secondKillId.toString());
        MiaoshaGoods miaoshaGoods;
        if (miaoshaJson == null) {
            miaoshaGoods = miaoshaGoodsMapper.selectByPrimaryKey(secondKillId);
            miaoshaJson = JsonUtil.Obj2String(miaoshaGoods);
            JedisUtil.setEx(Const.MIAOSHA_INFO, secondKillId.toString(), miaoshaJson, 60);
        }
        miaoshaGoods = JsonUtil.String2Obj(miaoshaJson, new TypeReference<MiaoshaGoods>() {
        });
        if (_noStockInRedisCache(secondKillId)) {
            _initStock(secondKillId, miaoshaGoods.getMisoshaStock());
        }
        if (_getStock(miaoshaGoods.getId()) <= 0) {
            JedisUtil.del(Const.MIAOSHA_STOCK, miaoshaGoods.getId().toString());
            return this._createRetMap(Const.STATUS_CODE.FAIL_CODE, "秒杀已经被抢购一空");
        }
        if (System.currentTimeMillis() < miaoshaGoods.getStartDate().getTime()) {
            return this._createRetMap(Const.STATUS_CODE.FAIL_CODE, "秒杀尚未开始");
        }
        if (System.currentTimeMillis() > miaoshaGoods.getEndDate().getTime()) {
            return this._createRetMap(Const.STATUS_CODE.FAIL_CODE, "秒杀已结束");
        }
        boolean isKill = miaoshaOrderMapper.countSecondKillByUserIdAndSecondKillId(userId, secondKillId) > 0;
        if (isKill) {
            return this._createRetMap(Const.STATUS_CODE.SUCCESS_CODE, "您已经成功一件了,不能再抢了");
        }
        JedisUtil.decr(Const.MIAOSHA_STOCK, secondKillId.toString());
        MiaoshaMessage miaoshaMessage = new MiaoshaMessage();
        miaoshaMessage.setUser(user);
        miaoshaMessage.setMiaoshaId(secondKillId);
        miaoshaMessage.setShippingId(shippingId);
        mqSender.sendMiaoSha(miaoshaMessage);
        return this._createRetMap(Const.STATUS_CODE.SUCCESS_CODE, "抢购成功");


    }

    public boolean _noStockInRedisCache(Long seckillId) {
        return JedisUtil.get(Const.MIAOSHA_STOCK, seckillId.toString()) == null;
    }

    public Long _getStock(Long seckillId) {
        return Long.valueOf(JedisUtil.get(Const.MIAOSHA_STOCK, seckillId.toString()));
    }

    public void _initStock(Long seckillId, Integer seckillStock) {
        JedisUtil.set(Const.MIAOSHA_STOCK, seckillId.toString(), seckillStock.toString());
    }

    public Map<String, Object> _createRetMap(Integer code, String msg) {
        Map<String, Object> map = Maps.newHashMap();
        map.put("code", code);
        map.put("msg", msg);
        return map;
    }

    @Transactional
    @Override
    public JsonData receiveOrder(User user, Long miaoshaId, Long shippingId) {
        Long orderId = System.currentTimeMillis();
        int effect = miaoshaGoodsMapper.updateMiaoShaStock(miaoshaId);
        if (effect > 0) {
            MiaoshaOrder miaoshaOrder = MiaoshaOrder.builder()
                    .orderId(orderId)
                    .secondKillId(miaoshaId)
                    .userId(user.getId())
                    .build();
            miaoshaOrderMapper.insertSelective(miaoshaOrder);
            MiaoshaGoods miaoshaGoods = miaoshaGoodsMapper.selectByPrimaryKey(miaoshaId);
            OrderInfo orderInfo = new OrderInfo();
            orderInfo.setUserId(user.getId());
            orderInfo.setGoodsId(miaoshaGoods.getGoodsId());
            orderInfo.setCreateTime(new Date());
            orderInfo.setShippingId(shippingId);
            orderInfo.setGoodsCount(Const.MIAO_SHA_GOOD_COUNT);
            orderInfo.setStatus(Const.ORDER_STATUS.NO_PAY);
            orderInfo.setOrderChannel(Const.ORDER_CHANNEL.PC);
            Goods goods = goodsMapper.selectByPrimaryKey(miaoshaGoods.getGoodsId());
            orderInfo.setGoodsName(goods.getGoodsName());
            orderInfo.setGoodsPrice(miaoshaGoods.getMiaoshaPrice());
            orderInfo.setId(orderId);
            orderInfoMapper.insertSelective(orderInfo);
            return JsonData.success("抢购成功～");
        } else {
            return JsonData.fail("下单失败，库存不足～");
        }

    }

    @Override
    public JsonData list() {
        List<MiaoshaGoods> miaoshaGoodsList = miaoshaGoodsMapper.getMiaoShaGoodByGoodsId(null);
        List<MiaoshaManageDTO> miaoshaManageDTOList = Lists.newArrayList();
        miaoshaGoodsList.forEach(miaoshaGoods -> miaoshaManageDTOList.add(adapt(miaoshaGoods)));
        return JsonData.success(miaoshaManageDTOList);
    }

    @Override
    public Map<String, Object> add(MiaoshaGoods miaoshaGoods) {

        int count = miaoshaGoodsMapper.insert(miaoshaGoods);
        if (count == 0) {
            return this._createRetMap(Const.STATUS_CODE.FAIL_CODE, "插入失败");
        }
        return this._createRetMap(Const.STATUS_CODE.FAIL_CODE, "插入成功");
    }

    public MiaoshaManageDTO adapt(MiaoshaGoods miaoshaGoods) {
        MiaoshaManageDTO miaoshaManageDTO = MiaoshaManageDTO.builder()
                .miaoshaId(miaoshaGoods.getId())
                .endTime(TimeUtil.formatDate(miaoshaGoods.getEndDate()))
                .startTime(TimeUtil.formatDate(miaoshaGoods.getStartDate())).build();
        int finishCount = miaoshaOrderMapper.countSecondKillByUserIdAndSecondKillId(null, miaoshaGoods.getId());
        miaoshaManageDTO.setHasFinishedCount(finishCount);
        miaoshaManageDTO.setTargetCount(finishCount + miaoshaGoods.getMisoshaStock());
        if (JedisUtil.get(Const.COUNT_PREFIX, miaoshaGoods.getId().toString()) == null) {
            miaoshaManageDTO.setScanCount(0);
        } else {
            miaoshaManageDTO.setScanCount(Integer.valueOf(JedisUtil.get(Const.COUNT_PREFIX, miaoshaGoods.getId().toString())));
        }
        return miaoshaManageDTO;
    }


}
